﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace KTDS_IPBS_CLASSLIBRARY
{
    public struct InfoTraceroute
    {
        public int Num_Hop;
        public String EndPoint;
        public int StartTime;
        public int StopTime;
        public int ProcessTime;
        public String Info_Message;
        public String Hostname;
    }

    class C_Traceroute
    {
        //=========================== 실제 - 트래이스 실행 함수 ===========================
        public List<string> ExcuteTraceroute(String ipinfo)
        {
            List<string> ResultTraceroute = new List<string>();

            byte[] data = new byte[512];
            int recv, timestart, timestop;
            Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
            IPHostEntry iphe = Dns.Resolve(ipinfo);
            IPEndPoint iep = new IPEndPoint(iphe.AddressList[0], 0);
            EndPoint ep = (EndPoint)iep;
            C_ICMP packet = new C_ICMP();
            packet.Type = 0x08;
            packet.Code = 0x00;
            packet.Checksum = 0;
            Buffer.BlockCopy(BitConverter.GetBytes(1), 0, packet.Message, 0, 2);
            Buffer.BlockCopy(BitConverter.GetBytes(1), 0, packet.Message, 2, 2);
            data = Encoding.ASCII.GetBytes("test");
            Buffer.BlockCopy(data, 0, packet.Message, 4, data.Length);
            packet.MessageSize = data.Length + 4;
            int packetsize = packet.MessageSize + 4;
            UInt16 chcksum = packet.getChecksum();
            packet.Checksum = chcksum;
            host.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1);
            int badcount = 0;

            for (int i = 1; i < 50; i++)
            {
                host.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, i);
                timestart = Environment.TickCount;
                host.SendTo(packet.getBytes(), packetsize, SocketFlags.None, iep);
                try
                {
                    data = new byte[512];
                    recv = host.ReceiveFrom(data, ref ep);
                    timestop = Environment.TickCount;
                    C_ICMP response = new C_ICMP(data, recv);
                    if (response.Type == 11)
                    {
                        ResultTraceroute.Add(ep.ToString().Remove((ep.ToString().Length - 2), 2));
                    }

                    if (response.Type == 0)
                    {
                        ResultTraceroute.Add(ep.ToString().Remove((ep.ToString().Length - 2), 2));
                        break;
                    }
                    badcount = 0;
                }
                catch (SocketException)
                {
                    ResultTraceroute.Add("*");
                    badcount++;
                    if (badcount == 2)
                    {
                        ResultTraceroute.Add("*");
                        break;
                    }
                }
            }

            host.Close();
            return ResultTraceroute;
        }
    }
}
